<template>
  <div class="date-picker">
    <div class="closeBg" @click="show = false" v-if="show"></div>
    <div :class="['date-ipt', redTips ? 'error' : '']" @click="show = !show">
        <label class="name" v-if="setTime">
            <template v-if="pickerOptions.isAllDay">{{date}}</template>
            <template v-else>{{setTime}}</template>
        </label>
        <label class="name placeholder" v-else>{{placeholder ? placeholder : '请选择'}}</label>
    </div>
    <div :class="['date-calendar', show ? 'date-visible' : '']" :style="calendarPosition">
        <div class="date-header" v-if="type == 'datetime'">
            <div :class="['date-cell', date ? '' : 'placeholder']">
                <label class="name">{{date || '日期'}}</label>
            </div>
            <div :class="['date-cell', time ? '' : 'placeholder']">
                <SelectItem :customStyle="customStyle" :modelValue="time" placeholder="选择时间" :data="timeData" value-name="name" @change="getTime"></SelectItem>
            </div>
        </div>
        <div class="calendar-date">
            <div class="calendar-title">
                <double-left theme="outline" size="14" fill="#75878a" @click="changeYear('preview')"/>
                <left theme="outline" size="14" fill="#75878a" @click="changeMonth('preview')"/>
                <p class="title-time" v-if="nowDate.value">{{nowDate.value.year + ' 年 ' + nowDate.value.month + ' 月 '}}</p>
                <right theme="outline" size="14" fill="#75878a" @click="changeMonth('next')"/>
                <double-right theme="outline" size="14" fill="#75878a" @click="changeYear('next')"/>
            </div>
            <div class="week-time">
                <div class="week" v-for="item in week" :key="item.id">{{item}}</div>
            </div>
            <div class="calendar-content">
                <div class="calendar-month-cell" v-for="item in month.value" :key="item.id">
                    <div :class="['calendar-month-date', cell.disable ? 'disabled' : '', cell.isDay ? 'picker-today' : '', date == cell.fullDate ? 'current' : '']" v-for="cell in item" :key="cell.id" @click="getDay(cell)">{{cell.date}}</div>
                </div>
            </div>
        </div>
        <div class="calendar-footer">
            <button class="cancel btn" @click="cancelCalendar">取消</button>
            <button class="submit btn" @click="sumitCalendar">确定</button>
        </div>
    </div>
  </div>
</template>

<script>
import { reactive, onMounted, toRefs, watch, ref } from 'vue'
import { DoubleLeft, Left, DoubleRight, Right } from '@icon-park/vue-next'
import Calendar from '../lib/calendar.js'
import SelectItem from '../SelectItem/index.vue'
import { cutTime } from '../lib/utils'
export default {
    name: 'DatePicker',
    props: {
        placeholder: {
            type: String,
            default: ''
        },
        modelValue: {
            type: String,
            default: ''
        },
        pickerOptions: {
            type: Object,
            default: () => {
                return {}
            }
        },
        type: {
            type: String,
            default: 'date'
        }
    },
    emits: ['update:modelValue'],
    components: {
        DoubleLeft,
        DoubleRight,
        Left,
        Right,
        SelectItem
    },
    setup(props, context) {
        const { pickerOptions, modelValue } = toRefs(props)
        let date = ref(null)
        let time = ref(null)
        let show = ref(false)
        let setTime = ref(null)
        let redTips = ref(false)
        let calendarPosition = ref({
            top: `26px`,
            left: `1px`,
            bottom: `unset`,
            right: `unset`
        })
        const customStyle = {
            border: 'none',
            padding: '0 8px'
        }
        const state = reactive({
            month: ref([]),
            calc: '',
            nowDate: ref({}),
            week: ['一', '二', '三', '四', '五', '六', '日'],
            timeData: cutTime()
        })
        const changeYear = (type) => {
            if(type == 'preview') {
                const preDate = state.calc.getDate(state.nowDate.value.fullDate, -1 * 12, 'month').fullDate
                state.calc.setDate(preDate)
                state.nowDate.value = state.calc.getInfo(preDate)
            }else{
                const nextDate = state.calc.getDate(state.nowDate.value.fullDate, 1 * 12, 'month').fullDate
                state.calc.setDate(nextDate)
                state.nowDate.value = state.calc.getInfo(nextDate)
            }
           state.month.value = state.calc.month
        }
        const changeMonth = (type) => {
            if(type == 'preview') {
                const preDate = state.calc.getDate(state.nowDate.value.fullDate, -1, 'month').fullDate
                state.calc.setDate(preDate)
                state.nowDate.value = state.calc.getInfo(preDate)
            }else{
                const nextDate = state.calc.getDate(state.nowDate.value.fullDate, 1, 'month').fullDate
                state.calc.setDate(nextDate)
                state.nowDate.value = state.calc.getInfo(nextDate)
            }
           state.month.value = state.calc.month
        }
        const getDay = (e) => {
            date.value = e.fullDate
        }
        const cancelCalendar = () => {
            show.value = false
        }
        const sumitCalendar = () => {
            if(time.value){
                context.emit('update:modelValue', date.value + ' ' + time.value)
            }else{
                context.emit('update:modelValue', date.value)
            }
            show.value = false
            if(time.value) {
                setTime.value = date.value + ' ' + time.value
            }else{
                setTime.value = date.value
            }
        }
        const clearValue = () => {
            context.emit('update:modelValue', '')
            setTime.value = ''
        }
        const checkDisabled = (val) => {
            let initTime = ''
            if(val.isAllDay){
                initTime = new Date(new Date(val.disabledDate + ':00').toLocaleDateString()).getTime()
            }else{
                initTime = new Date(val.disabledDate).getTime()
            }
            const current = new Date(date.value + ' ' + time.value).getTime()
            if(val.type == 'before') {
                // 之前的时间不能选
                if(current < initTime){
                    redTips.value = true
                }else{
                    redTips.value = false
                }
            }else{
                if(current > initTime){
                    redTips.value = true
                }else{
                    redTips.value = false
                }
            }
            return redTips.value
        } 
        const getTime = e => {
            if(e) {
                context.emit('update:modelValue', date.value + ' ' + e)
            }else{
                context.emit('update:modelValue', date.value)
            }
        }
        watch(() => pickerOptions.value,
            (val) => {
                if(val.disabledDate) {
                    checkDisabled(val)
                }
            },
            {
                deep: true
            }
        )
        watch(() => modelValue.value,
            (newVal, oldVal) => {
                const val = newVal || oldVal
                const splitTime = val.split(' ')
                date.value = splitTime[0]
                time.value = splitTime[1]
                if(time.value){
                    setTime.value = date.value + ' ' + time.value
                }else{
                    setTime.value = date.value
                }
            },
            {
                deep: true
            }
        )
        watch(() => show.value,
            () => {
                setPosition()
            }
        )
        const setPosition = () => {
            if(!document.getElementById('timeRef')) {
                const windowX = document.querySelector('.ssal-calendar').clientWidth
                const width = document.querySelector('.date-calendar').clientWidth
                const left = document.querySelector('.date-picker').offsetLeft
                if(windowX - width - left < 0) {
                    calendarPosition.value.left = `unset`
                    calendarPosition.value.right = 0
                }
                return false
            }
            const { offsetHeight, offsetTop, dataset } = document.getElementById('timeRef')
            let windowY = 0
            const height = 389
            if(dataset.type == 'scroll') {
                windowY = document.querySelectorAll('.scroll-container').clientHeight
            }else{
                windowY = document.querySelector('.ssal-calendar').clientHeight
            }
            const releaseY = windowY - offsetHeight - offsetTop
            if(releaseY < height) {
                calendarPosition.value.top = `unset`
                calendarPosition.value.bottom = `30px`
            }else{
                calendarPosition.value.top = `26px`
                calendarPosition.value.bottom = `unset`
            }
        }
        onMounted(() => {
            state.calc = new Calendar({
                date: new Date(),
                range: [],
            })
            state.calc.setDate(new Date())
            state.nowDate.value = state.calc.getInfo()
            state.month.value = state.calc.month
            checkDisabled(pickerOptions.value)
        })
        return {
            ...state,
            changeYear,
            changeMonth,
            getDay,
            date,
            time,
            show,
            customStyle,
            cancelCalendar,
            sumitCalendar,
            clearValue,
            setTime,
            redTips,
            calendarPosition,
            getTime
        }
    }
}
</script>

<style scoped lang="scss">
.date-picker{
    position: relative;
    width: 100%;
    .closeBg{
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 10;
    }
    .date-ipt{
        display: flex;
        align-items: center;
        border-bottom: 1px solid var(--ss-color-primary-light);
        padding-bottom: 5px;
        background: #fff;
        .name{
            flex: 1;
            overflow: hidden;
            font-size: 13px;
            cursor: pointer;
        }
        .option-btn{
            height: 18px;
            cursor: pointer;
            .option{
                height: 18px;
            }
            :deep(.i-icon){
                line-height: 10px;
                transition: .2s;
            }
        }
    }
    .error{
        border-bottom-color: var(--ss-color-error);
        .name{
            color: var(--ss-color-error);
        }
    }
    .placeholder{
        color: var(--ss-color-placeholder);
    }
    .date-calendar{
        position: absolute;
        left: 1px;
        z-index: 15;
        background: #fff;
        border-radius: 4px;
        box-shadow: rgba(67, 71, 85, 0.27) 0px 0px 0.25em, rgba(90, 125, 188, 0.05) 0px 0.25em 1em;
        margin-top: 2px;
        top: 26px;
        padding: 5px 0;
        width: 280px;
        visibility: hidden;
        opacity: 0;
        .date-header{
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid var(--ss-color-primary-light);
            padding: 0 5px 5px;
            .date-cell{
                flex: 1;
                padding: 5px 0;
                border-radius: 4px;
                border: 1px solid var(--ss-color-primary-light);
                font-size: 13px;
                margin-right: 5px;
                position: relative;
                &:last-child{
                    margin-right: 0;
                }
                .name{
                    padding: 0 8px;
                }
            }
        }
        .calendar-date{
            // max-height: 220px;
            display: flex;
            justify-content: space-between;
            flex-direction: column;
            .calendar-title{
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 5px 8px 12px;
                cursor: pointer;
                .title-time{
                    flex: 1;
                    overflow: hidden;
                    text-align: center;
                    font-size: 14px;
                    color: var(--ss-color-text-black);
                    cursor: default;
                }
                :deep(.i-icon){
                    line-height: 10px;
                    transition: .2s;
                }
            }
            .week-time{
                border-bottom: 1px solid var(--ss-color-primary-light);
                display: flex;
                justify-content: space-between;
                align-items: center;
                font-size: 13px;
                padding: 0 8px 8px;
                .week{
                    flex: 1;
                    text-align: center;
                }
            }
            .calendar-content{
                padding: 5px 8px;
                .calendar-month-cell{
                    display: flex;
                    flex-wrap: wrap;
                    align-items: center;
                    .calendar-month-date{
                        flex: 1;
                        overflow: hidden;
                        font-size: 12px;
                        text-align: center;
                        height: 40px;
                        line-height: 40px;
                        color: var(--ss-color-text-gery);
                        position: relative;
                        cursor: pointer;
                    }
                    .disabled{
                        color: var(--ss-color-text-light-gery);
                    }
                    .picker-today{
                        color: var(--ss-color-primary);
                        font-weight: bold;
                    }
                    .current{
                        color: var(--ss-color-primary);
                        font-weight: bold;
                        &::after{
                            content: '';
                            position: absolute;
                            z-index: -1;
                            width: 25px;
                            height: 25px;
                            top: 0;
                            bottom: 0;
                            left: 0;
                            right: 0;
                            margin: auto;
                            background: var(--ss-color-primary-light);
                            border-radius: 50%;
                        }
                    }
                } 
            }
        }
        .calendar-footer{
            display: flex;
            justify-content: flex-end;
            align-items: center;
            padding: 5px 8px 0;
            border-top: 1px solid var(--ss-color-primary-light);
            .btn{
                border-radius: 2px;
                padding: 3px 12px;
                margin-right: 5px;
                cursor: pointer;
                box-sizing: border-box;
                transition: .1s;
                font-size: 12px;
                &:last-child{
                    margin-right: 0;
                }
            }
            .cancel{
                background: var(--ss-color-primary-light);
                color: var(--ss-color-primary);
            }
            .submit{
                background: var(--ss-color-primary);
                color: var(--ss-color-primary-light);
            }
        }
    }
    .date-visible{
        visibility: visible;
        opacity: 1;
    }
}
[data-theme='dark']{
    .date-picker .date-calendar {
        background: var(--next-color-disabled);
    }
    .date-picker .calendar-date .calendar-title .title-time{
        color: var(--next-color-white);
    }
    .date-picker .calendar-date .week-time{
        color: var(--next-color-white);
        border-color: var(--next-border-color-light);
    }
    .date-picker .date-calendar .calendar-footer{
        border-color: var(--next-border-color-light);
    }
    .date-picker .date-calendar .calendar-footer .cancel {
        background: transparent;
        border: 1px solid var(--el-color-primary);
        box-sizing: border-box;
    }
}
</style>